{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# LlamaIndex Bottoms-Up Development - LLMs and Prompts\n",
    "This notebook walks through testing an LLM using the primary prompt templates used in llama-index."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import openai\n",
    "import os\n",
    "\n",
    "openai.api_key = \"YOUR_API_KEY\"\n",
    "os.environ[\"OPENAI_API_KEY\"] = \"YOUR_API_KEY\""
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Setup\n",
    "In this section, we load a test document, create an LLM, and copy prompts from llama-index to test with."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First, let's load a quick document to test with. Right now, we will just load it as plain text, but we can do other operations later!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open(\"../docs/getting_started/starter_example.md\", \"r\") as f:\n",
    "    text = f.read()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we create our LLM!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index.llms import OpenAI\n",
    "llm = OpenAI(model=\"gpt-3.5-turbo\", temperature=0)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "LlamaIndex uses some simple templates under the hood for answering queries -- mainly a `text_qa_template` for obtaining initial answers, and a `refine_template` for refining an existing answer when all the text does not fit into one LLM call.\n",
    "\n",
    "Let's copy the default templates, and test out our LLM with a few questions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "from llama_index import Prompt\n",
    "\n",
    "text_qa_template = Prompt(\n",
    "    \"Context information is below.\\n\"\n",
    "    \"---------------------\\n\"\n",
    "    \"{context_str}\\n\"\n",
    "    \"---------------------\\n\"\n",
    "    \"Given the context information and not prior knowledge, \"\n",
    "    \"answer the question: {query_str}\\n\"\n",
    ")\n",
    "\n",
    "refine_template = Prompt(\n",
    "    \"We have the opportunity to refine the original answer \"\n",
    "    \"(only if needed) with some more context below.\\n\"\n",
    "    \"------------\\n\"\n",
    "    \"{context_msg}\\n\"\n",
    "    \"------------\\n\"\n",
    "    \"Given the new context, refine the original answer to better \"\n",
    "    \"answer the question: {query_str}. \"\n",
    "    \"If the context isn't useful, output the original answer again.\\n\"\n",
    "    \"Original Answer: {existing_answer}\"\n",
    ")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, lets test a few questions!\n",
    "\n",
    "## Text QA Template Testing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "To install LlamaIndex, you can follow the installation steps provided in the \"installation\" guide.\n"
     ]
    }
   ],
   "source": [
    "question = \"How can I install llama-index?\"\n",
    "prompt = text_qa_template.format(context_str=text, query_str=question)\n",
    "response = llm.complete(prompt)\n",
    "print(response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "To create an index using LlamaIndex, you need to follow these steps:\n",
      "\n",
      "1. Download the LlamaIndex repository by cloning it from GitHub.\n",
      "2. Navigate to the `examples/paul_graham_essay` folder in the cloned repository.\n",
      "3. Create a new Python file and import the necessary modules: `VectorStoreIndex` and `SimpleDirectoryReader`.\n",
      "4. Load the documents from the `data` folder using `SimpleDirectoryReader('data').load_data()`.\n",
      "5. Build the index using `VectorStoreIndex.from_documents(documents)`.\n",
      "6. To persist the index to disk, use `index.storage_context.persist()`.\n",
      "7. To reload the index from disk, use the `StorageContext` and `load_index_from_storage` functions.\n",
      "\n",
      "Note: This answer assumes that you have already installed LlamaIndex and have the necessary dependencies.\n"
     ]
    }
   ],
   "source": [
    "question = \"How do I create an index?\"\n",
    "prompt = text_qa_template.format(context_str=text, query_str=question)\n",
    "response = llm.complete(prompt)\n",
    "print(response.text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "```python\n",
      "from llama_index import VectorStoreIndex, SimpleDirectoryReader\n",
      "\n",
      "documents = SimpleDirectoryReader('data').load_data()\n",
      "index = VectorStoreIndex.from_documents(documents)\n",
      "```"
     ]
    }
   ],
   "source": [
    "question = \"How do I create an index? Write your answer using only code.\"\n",
    "prompt = text_qa_template.format(context_str=text, query_str=question)\n",
    "response_gen = llm.stream_complete(prompt)\n",
    "for response in response_gen:\n",
    "    print(response.delta, end=\"\")"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Refine Template Testing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "To create an index using LlamaIndex, follow these steps:\n",
      "\n",
      "```python\n",
      "from llama_index import VectorStoreIndex, SimpleDirectoryReader\n",
      "\n",
      "# Load the documents from the 'data' folder\n",
      "documents = SimpleDirectoryReader('data').load_data()\n",
      "\n",
      "# Build the index\n",
      "index = VectorStoreIndex.from_documents(documents)\n",
      "\n",
      "# Persist the index to disk\n",
      "index.storage_context.persist()\n",
      "\n",
      "# Reload the index from disk\n",
      "from llama_index import StorageContext, load_index_from_storage\n",
      "\n",
      "storage_context = StorageContext.from_defaults(persist_dir=\"./storage\")\n",
      "index = load_index_from_storage(storage_context)\n",
      "```\n",
      "\n",
      "Make sure you have installed LlamaIndex and have the necessary dependencies.\n"
     ]
    }
   ],
   "source": [
    "question = \"How do I create an index? Write your answer using only code.\"\n",
    "existing_answer = \"\"\"To create an index using LlamaIndex, you need to follow these steps:\n",
    "\n",
    "1. Download the LlamaIndex repository by cloning it from GitHub.\n",
    "2. Navigate to the `examples/paul_graham_essay` folder in the cloned repository.\n",
    "3. Create a new Python file and import the necessary modules: `VectorStoreIndex` and `SimpleDirectoryReader`.\n",
    "4. Load the documents from the `data` folder using `SimpleDirectoryReader('data').load_data()`.\n",
    "5. Build the index using `VectorStoreIndex.from_documents(documents)`.\n",
    "6. To persist the index to disk, use `index.storage_context.persist()`.\n",
    "7. To reload the index from disk, use the `StorageContext` and `load_index_from_storage` functions.\n",
    "\n",
    "Note: This answer assumes that you have already installed LlamaIndex and have the necessary dependencies.\"\"\"\n",
    "prompt = refine_template.format(context_msg=text, query_str=question, existing_answer=existing_answer)\n",
    "response = llm.complete(prompt)\n",
    "print(response.text)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Chat Example\n",
    "The LLM also has a `chat` method that takes in a list of messages, to simulate a chat session. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "assistant: To create an index, you will need to follow these general steps:\n",
      "\n",
      "1. Determine the purpose and scope of your index: Decide what information you want to include in your index and what it will be used for. This will help you determine the structure and content of your index.\n",
      "\n",
      "2. Identify the items to be indexed: Determine the specific items or topics that you want to include in your index. For example, if you are creating an index for a book, you might want to index chapters, sections, and important concepts.\n",
      "\n",
      "3. Create a list of index terms: Identify the key terms or phrases that will be used to reference each item in your index. These terms should be concise and descriptive.\n",
      "\n",
      "4. Organize the index terms: Determine the hierarchical structure of your index. You can use headings, subheadings, and indentation to create a logical and organized structure.\n",
      "\n",
      "5. Assign page numbers or locations: For each index term, identify the page number or location where the item can be found. This will help users quickly locate the information they are looking for.\n",
      "\n",
      "6. Format the index: Use a consistent and clear formatting style for your index. You can use software tools like Microsoft Word or Adobe InDesign to create a professional-looking index.\n",
      "\n",
      "7. Review and revise: Once you have created your index, review it carefully to ensure accuracy and completeness. Make any necessary revisions or updates before finalizing your index.\n",
      "\n",
      "Remember, creating an index can be a time-consuming process, so it's important to plan and allocate enough time to complete it accurately.\n"
     ]
    }
   ],
   "source": [
    "from llama_index.llms import ChatMessage\n",
    "\n",
    "chat_history = [\n",
    "    ChatMessage(role=\"system\", content=\"You are a helpful QA chatbot that can answer questions about llama-index.\"),\n",
    "    ChatMessage(role=\"user\", content=\"How do I create an index?\"),\n",
    "]\n",
    "\n",
    "response = llm.chat(chat_history)\n",
    "print(response.message)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "\n",
    "In this notebook, we covered the low-level LLM API, and tested out some basic prompts with out documentation data."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
